#!/usr/bin/env python
#
# Copyright 2010 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# NOTE: Not tests for this file as it will be replaced with standard
# version that includes tests.

"""Use Google App Engine libraries in normal Python scripts.

This module is useful for automatically configuring shell and Python
scripts to work with Google App Engine libraries.

All modifications to sys.path are placed at the end of the list, so App Engine
dependencies will not override previously installed libraries.  sys.path is
configured based on the following rules:

  - If the App Engine SDK directory is already in the python path, it will
    configure sys.path to load all modules from that directory.

  - If APPENGINE_HOME is set in the environment, it will check to see if
    that directory exists and if so, will use that.  If APPENGINE_HOME
    is set, it will not attempt to check any other locations for installation.

  - If APPENGINE_HOME is not set and the App Engine SDK is not installed in the
    path, it will attempt to use in the platform specific default SDK
    installation location.

Importing in to Python:

  If this module is placed in to the PYTHONPATH of an executing Python
  program, it can be imported as a stand-alone top-level application.
  It will configure sys.path to contain all the necessary dependency
  libraries.

    import use_appengine
    use_appengine.configure()

    from google.appengine.ext.bulkload import bulkloader_config
    import webob

Using in a shell environment:

  The use_appengine module can be run directly.  In this case it will print
  the commands necessary to properly configure the running shell environment.
  On a unix-like system it will look something like this.

    $ python use_appengine.py
    export PYTHONPATH=/existing/python/path:/usr/local/google_appengine:...
"""

__all__ = ['DEFAULT_APPENGINE_HOME',
           'configure',
           'get_appengine_home',
           'import_appengine_paths',
           'main',
]

import logging
import os
import sys


DEFAULT_APPENGINE_HOME = os.path.abspath(
    os.path.join(sys.prefix, 'google_appengine'))


def get_appengine_home():
  """Get app engine home from environment or use default location.

  Returns:
    Location of appengine home as read from the environment or using
    the default location.  None if appengine directory is not found.
  """
  home = os.environ.get('APPENGINE_HOME')
  if home is not None:
    if os.path.isdir(home):
      return home
    else:
      logging.error('APPENGINE_HOME is set to a directory that does not exist.')
      return None

  try:
    import google
  except ImportError:
    pass
  else:
    return os.path.dirname(os.path.dirname(google.__file__))

  if os.path.isdir(DEFAULT_APPENGINE_HOME):
    return DEFAULT_APPENGINE_HOME
  elif os.path.isdir('/usr/local/google_appengine'):
    return '/usr/local/google_appengine'
  else:
    logging.error('App Engine is not installed in default location: %s',
                  DEFAULT_APPENGINE_HOME)
    return None


def import_appengine_paths(appengine_home=None, importer=__import__):
  """Import google.appengine.tools.appengine_paths.

  This method will add appengine_home to the Python path.

  Args:
    appengine_home: Location where App Engine SDK is stored.  If not
      provided, will attempt to determine from environment.
    importer: Alternate importer to use for module loading.

  Returns:
    appengine_paths module as loaded from known configuration.

  Raises:
    ImportError when App Engine SDK is not found or os too old to contain
      appengine_paths.
  """
  global appengine_paths
  try:

    from google.appengine.tools import appengine_paths
  except ImportError:
    if appengine_home is None:
      appengine_home = get_appengine_home()
    if appengine_home is None:
      raise
    sys.path.append(appengine_home)
    try:
      appengine_paths = importer('google.appengine.tools.appengine_paths',
                                 globals(),
                                 locals(),
                                 ['appengine_paths'])
    except ImportError:
      from glp import appengine_paths
  return appengine_paths


def configure(appengine_home=None, importer=__import__):
  """Configure current Python runtime to use App Engine libraries.

  Args:
    paths: System path to configure.  If not provided will configure sys.path.
    appengine_home: Location where App Engine SDK is stored.  If not
      provided, will attempt to determine from environment.
    importer: Alternate importer to use for module loading.

  Raises:
    ImportError when App Engine SDK is not found or is too old to contain
      appengine_paths.
  """
  if appengine_home is None:
    appengine_home = get_appengine_home()
  import_appengine_paths(appengine_home,
                         importer=importer).set_paths(appengine_home)

def main(argv=None):
  """Main function.

  Called when executing this module as a script.  Output commands necessary
  to configure the environment to use App Engine and dependencies.  See
  import_appengine.main() for details.

  Args:
    argv: Arguments as passed in from command line.  If not provided will
      use sys.argv.
  """
  if argv is None:
    argv = sys.argv
  import_appengine_paths().main(argv, appengine_home=get_appengine_home())

if __name__ == '__main__':
  main(sys.argv)
else:
  configure()
